import { shallowRef, watch, ref } from "vue"
import { db } from "@/config/data";
import { useWebSocket, useInterval } from 'vue-hooks-plus'
import { useStore } from 'vuex';
import { v4 as uuidv4 } from 'uuid';
import { getFriendDetail } from '@/server/friend'
import { getGroupDetail, sendForward } from '@/server/friend'
export const createSession = async (id, isGroup) => {
  //无会话窗口, 要查相关信息

  let result = isGroup ? await getGroupDetail(id) : await getFriendDetail(id)
  if (isGroup) result = { ...result.group, ...result?.set }
  const customMsg = {
    msgId: uuidv4(),
    pushType: "MSG",
    timestamp: new Date().getTime(),
    msgContent: {
      content: "",
      disturb: result?.disturb,
      msgType: "TEXT",
      top: result?.top
    },
    fromInfo: {
      nickName: result?.nickName,
      portrait: result?.portrait,
      userId: result?.userId,
      userType: 'normal',
    },
    groupInfo: {
      nickName: result?.name,
      portrait: result?.portrait,
      userId: result?.groupId,
    }
  }
  isGroup ? customMsg.fromInfo = {} : customMsg.groupInfo = {}
  return customMsg
}



const multiterminalProcessing = async (res, store, msgCustomType) => {
  const search = msgCustomType === 1 ? { groupId: res?.groupInfo?.userId, msgCustomType } : { userId: res?.fromInfo?.chatId, msgCustomType }
  const bands = await db.conversation.get(search) //查询窗口
  // return
  //自己发消息插入数据库
  const customMsg = {
    msgId: res?.msgId,
    pushType: "MSG",
    timestamp: res?.timestamp,
    msgContent: res?.msgContent,
    fromInfo: {
      nickName: res?.fromInfo?.nickName,
      portrait: res?.fromInfo?.portrait,
      userId: res?.fromInfo?.userId,
      userType: "normal",
    },
    groupInfo: {
      nickName: res?.groupInfo?.nickName,
      portrait: res?.groupInfo?.portrait,
      userId: res?.groupInfo?.userId,
    },
    hasRead: 0
  }
  if (bands) {
    customMsg.uuid = bands?.uuid
    if (msgCustomType === 0) customMsg.groupInfo = {}
    await handelNotice(customMsg, store)
  } else {
    // 没有此窗口,需要创建会话
    const isGroup = msgCustomType === 1
    const id = isGroup ? res?.groupInfo?.userId : res?.fromInfo?.chatId
    const newMsg = await createSession(id, isGroup)
    await handelNotice(newMsg, store)
    await multiterminalProcessing(res, store, msgCustomType)
  }

}


const getState = (res) => {
  //res uuid  是否会话窗口id 
  const groupId = res?.groupInfo?.userId
  const userId = res?.fromInfo?.userId
  // msgCustomType 0 普通消息   1 群聊消息   ....其他消息类别
  let msgCustomType = 0
  if (groupId) msgCustomType = 1
  if (userId && !groupId) msgCustomType = 0

  const isGroup = msgCustomType === 1
  const newData = {
    lastMsg: res?.msgContent?.content,
    ...res?.msgContent,
    timestamp: res?.timestamp,
    hasRead: 1,
    ...(res.fromInfo || {}),
    msgCustomType,
    msgId: res?.msgId,
    uuid: uuidv4()
  }
  if (msgCustomType === 1) {
    //群聊
    const data = {
      groupPortrait: res?.groupInfo?.portrait,
      groupName: res?.groupInfo?.nickName,
      groupId,
    }
    Object.assign(newData, data)
  }

  let search = isGroup ? { groupId, msgCustomType } : { userId, msgCustomType }

  if (res?.uuid) search = { uuid: res?.uuid } //有会话窗口,直接用会话窗口搜

  return {
    groupId,
    msgCustomType,
    userId,
    newData,
    isGroup,
    search
  }
}


//检查当前选中的窗口,是否和返回的消息是同一个窗口,如果是同一个窗口,消息数量不显示
const checkSessionFocus = (store, bands) => {
  const { uuid: sessionId } = store.state.selectSession
  let addNum = 0
  let focusing = false
  if (sessionId !== bands?.uuid) {
    addNum = bands.hasRead + 1
  } else {
    focusing = true
  }
  return {
    addNum,
    focusing
  }
}


//插入消息详情
const insertMessage = async (state, store) => {
  // 以下 插入聊天数据的
  try {
    const newState = { ...state }
    const msgCustomType = state.msgCustomType
    const actionForm = ['privateChat', 'groupChat']
    //上面插入后,会给原始对象新增一个唯一id
    if (state?.id) delete newState?.id
    if (newState?.msgType === 'REVOKE') {
      //撤回相关逻辑
      const isSelf = store.state.userInfo.userId === newState?.userId //是否是自己撤回的
      newState.content = isSelf ? '我撤回了一条信息' : (newState?.nickName + '撤回了一条信息')
      const msgId = state.content
      await Reflect.get(db, actionForm[msgCustomType]).where({ msgId }).modify(newState)
      return
    }
    await Reflect.get(db, actionForm[msgCustomType]).add(newState)
  } catch (err) {
    console.log(err, '插入错误')
  }
}


//更新左侧会话列表
const putConversation = async (res, search, newData, msgCustomType, store) => {
  const state = { ...newData }
  const bands = await db.conversation.get(search) //当前是否已经有窗口了
  if (bands) state.uuid = bands.uuid // 窗口存在,直接使用窗口的uuid重写
  // 插入左侧列表的数据
  if (bands) {
    const { addNum } = checkSessionFocus(store, bands)
    if (res?.uuid) {
      let permitInsert = true //是否允许更新消息
      //res有uuid 则是自己拼接发送的消息
      const content = res?.msgContent?.content || bands?.content
      const editInfo = {
        timestamp: res.timestamp,
        msgType: res?.msgContent.msgType,
        lastMsg: content,
        hasRead: addNum,
      }

      if (res?.hasRead === 0) {
        // 自己发消息，pc接受时。创建了窗口，发送后取消数量
        editInfo.hasRead = 0
      }
      if (editInfo?.msgType === 'REVOKE') {
        //检查是否存在这一条消息,多端的msg不一定正确
        const actionForm = ['privateChat', 'groupChat']
        const msgId = state.content
        const hasMsg = await Reflect.get(db, actionForm[msgCustomType]).get({ msgId })
        hasMsg ? (editInfo.lastMsg = '我撤回了一条信息') : (permitInsert = false)
      }
      if (permitInsert) await db.conversation.update(bands?.id, editInfo)
    } else {
      // 对方发送的消息
      const editInfo = { ...state, hasRead: addNum }
      if (editInfo?.msgType === 'REVOKE') {
        editInfo.lastMsg = editInfo?.nickName + '撤回了一条信息'
      }
      await db.conversation.where(search).modify(editInfo)
    }
  } else {
    if (state.content === '') {
      state.hasRead = 0
    }
    await db.conversation.add(state)
  }
  return state
}

export const handelNotice = async (res, store) => {
  const { newData, msgCustomType, search } = getState(res)
  // 处理多端等问题 自己的消息,转为本地发送一条消息，但是不发请求
  if (res?.fromInfo?.userType === 'self') {
    await multiterminalProcessing(res, store, msgCustomType)
    return
  }
  const state = await putConversation(res, search, newData, msgCustomType, store) //插入左侧数据逻辑
  await insertMessage(state, store) // 插入消息逻辑
  return state
}


//批量转发
export const bulkForwarding = async (msg, store) => {
  const actionForm = ['privateChat', 'groupChat']
  const sendAction = async (row) => {
    const { isGroup, search, groupId, userId } = getState(row)
    const bands = await db.conversation.get(search)
    const waitMsg = row?.waitMsg
    const hasband = async () => {
      const msgCustomType = bands?.msgCustomType
      const lastMsg = waitMsg[waitMsg.length - 1]
      const editInfo = {
        timestamp: lastMsg?.timestamp,
        msgType: lastMsg?.msgContent.msgType,
        lastMsg: lastMsg?.msgContent?.content,
        hasRead: 0,
      }
      await db.conversation.update(bands?.id, editInfo)
      const insertData = waitMsg.map(item => {
        const { newData } = getState(item)
        delete newData?.id
        newData.uuid = bands.uuid
        return newData
      })
      await Reflect.get(db, actionForm[msgCustomType]).bulkAdd(insertData)
    }
    if (bands) {
      await hasband()
    } else {
      const id = isGroup ? groupId : userId
      const newMsg = await createSession(id, isGroup)
      await handelNotice(newMsg, store)
      await sendAction(row)
    }
  }

  for (let index = 0; index < msg.length; index++) {
    const r = msg[index];
    await sendAction(r)
  }

  const parmas = {
    userInfo: msg.map(row => {
      const { groupId, userId, isGroup } = getState(row)
      const id = groupId || userId
      return {
        userId: id,
        talkType: isGroup ? 'GROUP' : 'SINGLE'
      }
    }),
    msgInfo: msg[0].waitMsg.map(row => {
      return {
        msgType: row?.msgContent.msgType,
        content: row?.msgContent.content,
        msgId: row?.msgId
      }
    })
  }
  const res = await sendForward(parmas)
  if (res.status === '0') {
    store.commit('saveSelectMessages', [])
    store.commit('saveDialogState', false)
    store.commit('saveSearchSelectItem', [])
    store.commit('saveOpenChecked', false)
    return true
  }
  return false
}

// 更新群相关信息的表单
const updateGroupInfo = async (state, res) => {
  if (res.msgContent?.msgType === 'ALERT' && res?.groupInfo?.userId) {
    // 更新群聊状态信息
    const groupId = res?.groupInfo?.userId
    const alertSubdivideType = res?.msgContent?.alertSubdivideType
    const bands = await db.groupInfo.get({ groupId })
    if (bands) {
      await db.groupInfo.update(bands.id, { alertSubdivideType })
    } else {
      await db.groupInfo.add({ groupId, alertSubdivideType, uuid: state.uuid })
    }
  }
}


// 置顶相关逻辑

const updateTopState = async (element, store) => {
  if (element?.msgContent?.friendTop?.friendId) {
    const { friendId: userId, top } = element?.msgContent?.friendTop
    //好友置顶
    const bands = await db.conversation.get({ userId, msgCustomType: 0 })
    if (bands) {
      await db.conversation.update(bands.id, { top })
    } else {
      const newMsg = await createSession(userId, false)
      const state = await handelNotice(newMsg, store)
      await db.conversation.where({ uuid: state.uuid }).modify({ top })
    }
  }
  if (element?.msgContent?.groupTop?.groupId) {
    //群置顶逻辑
    const { groupId, top } = element?.msgContent?.groupTop
    const bands = await db.conversation.get({ groupId, msgCustomType: 1 })
    if (bands) {
      await db.conversation.update(bands.id, { top })
    } else {
      const newMsg = await createSession(groupId, true)
      const state = await handelNotice(newMsg, store)
      await db.conversation.where({ uuid: state.uuid }).modify({ top })
    }
  }
}

export const useMainWebSokect = async () => {
  const store = useStore()
  const voucher = ref(process.env.VUE_APP_WSURL + `?token=${localStorage.getItem("Token")}&t=${new Date().getTime()}`)
  let msgTesk = [] //正在遍历的数据
  let waitTesk = [] //正在插入数据的时候,新进来的数据
  let nextHandel = false //是否正在插入数据
  const msgInterval = shallowRef()
  const { readyState, sendMessage, disconnect, connect } = useWebSocket(
    voucher,
    {
      onOpen: () => {

      },
      reconnectInterval: 1000 * 30,
      reconnectLimit: 20,
      onMessage: async msg => {
        const res = JSON.parse(msg.data)
        nextHandel ? waitTesk.push(res) : msgTesk.push(res) //
        clearInterval(msgInterval.value)
        msgInterval.value = setTimeout(async () => {
          nextHandel = true
          const msg = [...msgTesk, ...waitTesk]
          waitTesk = []
          try {
            for (let index = 0; index < msg.length; index++) {
              const element = msg[index];
              if (element.pushType === 'MSG') {
                const state = await handelNotice(element, store)
                await updateGroupInfo(state, element)
              }
              if (element.pushType === 'NOTICE') {
                await updateTopState(element, store)
              }
            }
          } catch (error) {
            console.log(error)
          } finally {
            msgTesk = []
            nextHandel = false
          }
        }, 100);
        if (res.pushType === 'MSG') {
          window.electronAPI.twinkle({ open: true })
        }
      },
      onClose: () => {
        // clearInterval?.value()
      },
      onError: err => {
        console.log(err)
      }
    }
  )
  clearInterval.value = useInterval(() => {
    if (readyState.value == 1) {
      sendMessage(JSON.stringify({ code: "0" }))
    }
  }, 1000 * 30)
}